// Copyright (C) 2024 wlly-lzh
// Created by wlly-lzh on 24-3-26
// Sequence List Queue 基于顺序表的队列

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

typedef struct LSeQueue LSeQueue;
struct LSeQueue {
	void **Data;
	int Head;   // 队列头的索引
	int Tail;   // 队列尾的索引
	int MaxSize; // 最大长度
};

void Error_LSeQueue_Malloc();
void Error_LSeQueue_Null();

LSeQueue *Create_LSeQueue(int Size){
	if(Size <= 0){
		printf("liblds/LSeQueue: Create Size is too less!\n");
		exit(2);
	}
	LSeQueue *newQueue;
	newQueue=(LSeQueue *)malloc(sizeof(LSeQueue));
	if(newQueue == NULL){
		Error_LSeQueue_Malloc();
		exit(3);
	}
	newQueue->Head=newQueue->Tail=0;
	newQueue->MaxSize=Size;
	newQueue->Data=(void **)malloc(sizeof(void *)*Size);
	if(newQueue->Data == NULL){
		Error_LSeQueue_Malloc();
		exit(3);
	}
	return newQueue;
}
void Clear_LSeQueue(LSeQueue *Queue){
	if(Queue != NULL){
		if(Queue->Head <= Queue->Tail){ // 队头在数组前面
			for(int i=Queue->Head; i<Queue->Tail; ++i){
				free(*(Queue->Data+i));
			}
		}else{                          // 队头在数组后面
			for(int i=0; i<Queue->Tail; ++i){
				free(*(Queue->Data+i));
			}
			for(int i=Queue->Head; i<=Queue->MaxSize-1; ++i){
				free(*(Queue->Data+i));
			}
		}
		Queue->Head=Queue->Tail=0;
	}else{
		Error_LSeQueue_Null();
		exit(4);
	}
}
void Destroy_LSeQueue(LSeQueue **Queue){
	Clear_LSeQueue(*Queue);
	free(*Queue);
	*Queue=NULL;
}
bool IsEmpty_LSeQueue(const LSeQueue *Queue){
	if(Queue == NULL){
		Error_LSeQueue_Null();
		exit(4);
	}
	if(Queue->Head == Queue->Tail)
		return true;
	else
		return false;
}
bool IsFull_LSeQueue(const LSeQueue *Queue){
	if(Queue == NULL){
		Error_LSeQueue_Null();
		exit(4);
	}
	if((Queue->Tail+1) % Queue->MaxSize == Queue->Head)
		return true;
	else
		return false;
}
bool En_LSeQueue(LSeQueue *Queue,void *Data){
	if(Queue == NULL){
		Error_LSeQueue_Null();
		exit(4);
	}
	if(Data == NULL){
		Error_LSeQueue_Null();
		return false;
	}
	if((Queue->Tail+1) % (Queue->MaxSize) != Queue->Head){
		*(Queue->Data+Queue->Tail)=Data;
		Queue->Tail=(Queue->Tail+1) % (Queue->MaxSize);
		return true;
	}else{
#ifdef _LINUX_PLATFORM_
		printf("\033[31mliblds/SeQueue warning: Full!\033[0m\n");
#else
		printf("liblds/SeQueue warning: Full!\n");
#endif
		return false;
	}
}
bool De_LSeQueue(LSeQueue *Queue,void **Data){
	if(Queue == NULL){
		Error_LSeQueue_Null();
		exit(4);
	}
	if(Queue->Head != Queue->Tail){
		*Data=*(Queue->Data + Queue->Head);
		Queue->Head=(Queue->Head+1) % (Queue->MaxSize);
		return true;
	}else{
#ifdef _LINUX_PLATFORM_
		printf("\033[31mliblds/LSeQueue warning: The Queue is Empty!\033[0m\n");
#else
		printf("liblds/LSeQueue warning: The Queue is Empty!\n");
#endif
		return false;
	}
}
bool GetHead_LSeQueue(const LSeQueue *Queue,void **Data){
	if(!IsEmpty_LSeQueue(Queue)){
		*Data=*(Queue->Data + Queue->Head);
		return true;
	}else
		return false;
}
#ifdef _LINUX_PLATFORM_
void Error_LSeQueue_Malloc(){
	printf("\033[31mliblds/LSeQueue: Malloc False!\033[0m\n");
}
void Error_LSeQueue_Null(){
	printf("\033[31mliblds/LSeQueue: The Parameter is Null!\033[0m\n");
}
#else
void Error_LSeQueue_Malloc(){
	printf("liblds/LSeQueue: Malloc False!\n");
}
void Error_LSeQueue_Null(){
	printf("liblds/LSeQueue: The Parameter is Null!\n");
}
#endif
